#pragma once

#include "Socket.hpp"

// 我们约定，我们的TCP服务端只进行IO工作，流式的IO，不对信息进行任何的加工处理
class TcpServer
{
    using tcphandler_t = std::function<bool(SockPtr, InetAddr)>;

public:
    TcpServer(int port = 8080) : _port(port),
                                 _listensockp(std::make_unique<TcpSocket>())
    {
    }
    ~TcpServer()
    {
        _listensockp->Close();
    }
    void InitServer(tcphandler_t handler)
    {
        _handler = handler;
        _listensockp->BuildTcpSocketMethod(_port);
    }

    void Loop()
    {
        _isrunning = true;
        while (_isrunning)
        {
            // 1. Accept
            InetAddr clientaddr;
            auto sockfd = _listensockp->Accepter(&clientaddr);
            if (sockfd == nullptr)
                continue;
            // 2. IO处理
            LOG(LogLevel::DEBUG) << "get a new client, info is: " << clientaddr.Addr();
            // sockfd->Recv();
            // sockfd->Send();

            pid_t id = fork();

            if (id == 0)
            {
                // 儿子进程
                // 这是之前的避免阻塞等待进程退出的办法

                // 我们要求孙子与儿子进程关闭监听描述符
                _listensockp->Close();

                if (fork() > 0)
                {
                    // 大于0的时儿子进程
                    exit(0);
                } // 此时儿子进程的儿子，也就是孙子并没进入if语句中
                // 此时就只有孙子进程在执行了

                // 进行回调
                _handler(sockfd,clientaddr);
                exit(0);
            }

            // 外面是父进程
            // 关闭连接返回的文件描述符，父进程不需要这个
            sockfd->Close();

            waitpid(id, nullptr, 0);
        }
        _isrunning = false;
    }

private:
    std::unique_ptr<Socket> _listensockp;
    int _port;

    bool _isrunning;
    tcphandler_t _handler;
};